package model.world;

import java.util.UUID;

import model.world.tile.ResourceType;
import model.world.tile.Tile;
import model.world.tile.TileDirection;

public class Chunk {
	private long cx, cy;
	private Tile[][] tiles;
	private Chunk[] neighbors;
	private UUID GUID;
	private static final int WIDTH = 30;
	private static final int HEIGHT = 30;
	
	public Chunk(long cx, long cy){
		GUID = UUID.randomUUID();
		this.cx = cx;
		this.cy = cy;
		neighbors = new Chunk[8];
		tiles = new Tile[WIDTH][HEIGHT];
		generateTerrain();
		stitchTiles();
	}

	private void generateTerrain() {
		ResourceType[] resources = ResourceType.values();
		double[] probRange = new double[resources.length - 1];
		for(int i = 0; i < resources.length - 1; i++){
			if(i == 0)
				probRange[i] = resources[i].getProbability();
			else
				probRange[i] = resources[i].getProbability() + probRange[i-1];
		}
		
		for(int i = 0; i < WIDTH; i++){
			for(int j = 0; j < HEIGHT; j++){
				double roll = Math.random();
				int sel_resource = 0;
				while(roll >= probRange[sel_resource]){
					sel_resource++;
					if(resources.length - 1 == sel_resource)
						break;
				}
				tiles[i][j] = resources[sel_resource].makeNew(i + WIDTH*cx, j + HEIGHT*cy , this);
			}
		}
	}
	
	private void stitchTiles(){
		for(int i = 0; i < WIDTH; i++){
			for(int j = 0; j < HEIGHT; j++){
				if(i != 0)
					tiles[i][j].setNeighbor(tiles[i-1][j], TileDirection.NORTH_WEST);
				if(i != WIDTH - 1)
					tiles[i][j].setNeighbor(tiles[i+1][j], TileDirection.SOUTH_EAST);
				if(j != 0)
					tiles[i][j].setNeighbor(tiles[i][j-1], TileDirection.NORTH);
				if(j != HEIGHT - 1)
					tiles[i][j].setNeighbor(tiles[i][j+1], TileDirection.SOUTH);
				if(i != 0 && j != HEIGHT - 1)
					tiles[i][j].setNeighbor(tiles[i-1][j+1], TileDirection.SOUTH_WEST);
				if(i != WIDTH - 1 && j != 0)
					tiles[i][j].setNeighbor(tiles[i+1][j-1], TileDirection.NORTH_EAST);
			}
		}
	}
	
	public void setNeighbor(ChunkDirection d, Chunk c){
		neighbors[d.toInt()] = c;
		c.neighbors[(d.toInt()+4)%8] = this;
		if(d == ChunkDirection.NORTH_WEST || d == ChunkDirection.SOUTH_EAST)
			return;
		if(d == ChunkDirection.NORTH_EAST)
			tiles[WIDTH-1][0].setNeighbor(c.tiles[0][HEIGHT-1], TileDirection.NORTH_EAST);
		if(d == ChunkDirection.SOUTH_WEST)
			tiles[0][HEIGHT-1].setNeighbor(c.tiles[WIDTH-1][0], TileDirection.SOUTH_WEST);
		if(d == ChunkDirection.NORTH)
			for(int i = 0; i < WIDTH; i++){
				tiles[i][0].setNeighbor(c.tiles[i][HEIGHT-1], TileDirection.NORTH);
				if(i != WIDTH-1)
					tiles[i][0].setNeighbor(c.tiles[i+1][HEIGHT-1], TileDirection.NORTH_EAST);
			}
		if(d == ChunkDirection.EAST)
			for(int i = 0; i < HEIGHT; i++){
				if(i != 0)
					tiles[WIDTH-1][i].setNeighbor(c.tiles[0][i-1], TileDirection.NORTH_EAST);
				tiles[WIDTH-1][i].setNeighbor(c.tiles[0][i], TileDirection.SOUTH_EAST);
			}
		if(d == ChunkDirection.SOUTH)
			for(int i = 0; i < WIDTH; i++){
				if(i != 0)
					tiles[i][HEIGHT-1].setNeighbor(c.tiles[i-1][0], TileDirection.SOUTH_WEST);
				tiles[i][HEIGHT-1].setNeighbor(c.tiles[i][0], TileDirection.SOUTH);
			}
		if(d == ChunkDirection.WEST)
			for(int i = 0; i < HEIGHT; i++){
				if(i != HEIGHT-1)
					tiles[0][i].setNeighbor(c.tiles[WIDTH-1][i+1], TileDirection.SOUTH_WEST);
				tiles[0][i].setNeighbor(c.tiles[WIDTH-1][i], TileDirection.NORTH_WEST);
			}
	}
	
	public Chunk getNeighbor(ChunkDirection d){
		return neighbors[d.toInt()];
	}
	
	public UUID getGUID(){
		return GUID;
	}
	
	public Tile getTile(int x, int y){
		return tiles[x][y];
	}
	
	public static int getWidth(){
		return WIDTH;
	}
	
	public static int getHeight(){
		return HEIGHT;
	}
	
	public long getCX(){
		return cx;
	}
	
	public long getCY(){
		return cy;
	}
	
	public void tick(){
		for(int i = 0; i < WIDTH; i++){
			for(int j = 0; j < HEIGHT; j++){
				tiles[i][j].tick();
			}
		}
	}
}
